package com.bitmain.mmst.miner.monitor.helper;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;

import com.bitmain.mmst.common.util.CommonUtil;
import com.bitmain.mmst.domain.MinerDetectDetail;
import com.bitmain.mmst.domain.MinerDetectFailure;
import com.bitmain.mmst.domain.MinerDetectPool;
import com.bitmain.mmst.domain.MinerType;
import com.bitmain.mmst.miner.monitor.executor.MinerCommandMessage;
import com.bitmain.ulnar.aider.UlnarAider;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

/**
 * 
 *
 * @author Richard - rui.wu@bitmain.com
 * @since 2016年7月28日 
 *
 */
public class DetectMessageParser {

	public static MinerDetectDetail processMessage(MinerCommandMessage message, Collection<MinerType> types){

		MinerDetectDetail detail = new MinerDetectDetail();

		detail.setMinerShelfId(message.getShelfId());
		detail.setMinerTypeId(message.getMinerTypeId());
		detail.setDetectTime(message.getExecuteTime());
		detail.setMinerHost(message.getHost());
		detail.setMinerMac(message.getMac());
		detail.setMinerPort(message.getPort());

		try {
			if(message.getStatsable()){
				System.out.println("程序进入到了stats解析");
				//解析出编译时间，固件版本
				JsonParser parser = new JsonParser();
				System.out.println(message.getHost()+":"+message.getStats());
				JsonObject object = parser.parse(processStats(message.getStats())).getAsJsonObject();
				JsonArray array = object.get("STATS").getAsJsonArray();
				JsonObject stats = array.get(0).getAsJsonObject();
				String compileTime = getString(stats,"CompileTime");
				String firmwareVersion = CommonUtil.formatFirmwareVersion(compileTime);
				detail.setCompileTime(compileTime);
				detail.setFirmwareVersion(firmwareVersion);
				System.out.println("解析后的compileTime:"+compileTime);
				System.out.println("解析后的firmwareVersion:"+firmwareVersion);

				//矿机类型，去掉矿机类型前面的"Antminer "，如"Antminer S9"只取"S9"
				String type = UlnarAider.defaultIfNull(stats.get("Type").getAsString(), "").toUpperCase().replace("ANTMINER ", "");
				detail.setMinerType(type);
				System.out.println("解析后的type为："+type);

				stats = array.get(1).getAsJsonObject();
				//解析出运行时间、电压、频率、5S算力、平均算力
				detail.setElapsed(getLong(stats,"Elapsed"));
				//detail.setVoltage(getDouble(stats,"Voltage"));
				detail.setFrequency(getInt(stats,"frequency"));
				detail.setHashReal(getDouble(stats,"GHS 5s"));
				detail.setHashAvg(getDouble(stats,"GHS av"));

				//解析出风扇数、每个风扇的转速、最大风扇转速、最小风扇转速
				int fanNum = getInt(stats,"fan_num");
				Integer[] fanSpeeds = new Integer[fanNum];
				int fanMinSpeed = Integer.MAX_VALUE;
				int fanMaxSpeed = 0;
				for(int i=1;i<=fanNum;i++){
					int speed = 0;
					JsonElement speedElement = stats.get("fan"+i);
					speed = speedElement.getAsInt();
					fanMinSpeed = Math.min(fanMinSpeed, speed);
					fanMaxSpeed = Math.max(fanMaxSpeed, speed);
					fanSpeeds[i-1] = speed;
				}
				detail.setFanSpeeds(fanSpeeds);
				detail.setFanNum(fanNum);
				detail.setFanMinSpeed(fanMinSpeed);
				detail.setFanMaxSpeed(fanMaxSpeed);

				//解析出温感数、每个温感器的温度、最大温度、最小温度
				int tempNum = getInt(stats,"temp_num");
				Integer[] tempValues = new Integer[tempNum];
				int tempMinValue = Integer.MAX_VALUE;
				int tempMaxValue = 0;
				for(int i=1;i<=tempNum;i++){
					int temp = 0;
					JsonElement tempElement = stats.get("temp"+i);
					temp = tempElement.getAsInt();
					tempMinValue = Math.min(tempMinValue, temp);
					tempMaxValue = Math.max(tempMaxValue, temp);
					tempValues[i-1] = temp;
				}
				detail.setTempValues(tempValues);
				detail.setTempNum(tempNum);
				detail.setTempMinValue(tempMinValue);
				detail.setTempMaxValue(tempMaxValue);

				//解析出链条数、每个链条的芯片数、每个链条的芯片分布情况、芯片总数(xo)、实际工作芯片数(o)
				int chainNum = 0;
				int chipNum = 0;
				int chipAllNum = 0;//根据数据得来的芯片数
				List<Integer> chainAcnList = new LinkedList<Integer>();//每个链条的芯片数
				List<String> chainAcsList = new LinkedList<String>();//芯片分布情况

				for(int i=1;i<=32;i++){
					int acn = getInt(stats,"chain_acn"+i);
					if(acn>0){
						chainNum++;
						chipAllNum += acn;
						String acs = getString(stats,"chain_acs"+i);
						chainAcnList.add(acn);
						chainAcsList.add(acs);
						for(int c=0;c<acs.length();c++){
							if(acs.charAt(c)=='o'){
								chipNum++;
							}
							if(acs.charAt(c)!=' '){
							}
						}
					}
				}
				detail.setChainNum(chainNum);
				detail.setChainAcns(chainAcnList.toArray(new Integer[chainNum]));
				detail.setChainAcss(chainAcsList.toArray(new String[chainNum]));
				detail.setChipAllNum(chipAllNum);
				detail.setChipNum(chipNum);
			}

			if(message.getPoolsable()){
				JsonParser parser = new JsonParser();
				JsonObject object = parser.parse(message.getPools()).getAsJsonObject();
				JsonArray array = object.get("POOLS").getAsJsonArray();

				MinerDetectPool[] pools = new MinerDetectPool[array.size()];
				for(int i=0;i<array.size();i++){
					JsonObject pool = array.get(i).getAsJsonObject();
					MinerDetectPool detectPool = new MinerDetectPool();

					detectPool.setId(getLong(pool , "POOL"));
					detectPool.setUrl(getString(pool , "URL"));
					detectPool.setUser(getString(pool , "User"));
					detectPool.setStatus(getString(pool , "Status"));
					detectPool.setPriority(getInt(pool , "Priority"));
					detectPool.setQuota(getDouble(pool , "Quota"));
					detectPool.setGetWorks(getLong(pool , "Getworks"));
					detectPool.setAccepted(getLong(pool , "Accepted"));
					detectPool.setRejected(getLong(pool , "Rejected"));
					detectPool.setDiscarded(getLong(pool , "Discarded"));
					detectPool.setStale(getLong(pool , "Stale"));
					detectPool.setDiff(getString(pool , "Diff"));
					detectPool.setDiff1Shares(getLong(pool , "Diff1 Shares"));
					detectPool.setDifficultyAccepted(getLong(pool , "Difficulty Accepted"));
					detectPool.setDifficultyRejected(getLong(pool , "Difficulty Rejected"));
					detectPool.setDifficultyStale(getLong(pool , "Difficulty Stale"));
					detectPool.setBestShare(getLong(pool , "Best Share"));
					pools[i] = detectPool;
					
					if(!StringUtils.equalsIgnoreCase("Alive", detectPool.getStatus())){
						continue;
					}
					//最近矿池，矿工号的判断
				}
				detail.setPools(pools);
			}

			if(BooleanUtils.isTrue(message.getSummaryable())){
				JsonParser parser = new JsonParser();
				JsonObject object = parser.parse(message.getSummary()).getAsJsonObject(); 
				JsonObject summary = object.get("SUMMARY").getAsJsonArray().get(0).getAsJsonObject();

				detail.setDifficultyAccepted(getInt(summary , "Difficulty Accepted"));
				detail.setDifficultyRejected(getInt(summary , "Difficulty Rejected"));
				detail.setFoundBlocks(getInt(summary , "Found Blocks"));
			}
		} catch (Exception e) {
			System.out.println("解析出错");
			e.printStackTrace();
		}
		System.out.println("detail的值："+detail.getFirmwareVersion()+detail.getMinerType());
		return detail;
	}

	public static MinerDetectFailure processFailure(MinerCommandMessage message) {
		MinerDetectFailure failure = new MinerDetectFailure();
		failure.setMinerShelfId(message.getShelfId());
		failure.setMinerHost(message.getHost());
		failure.setMinerMac(message.getMac());
		failure.setMinerPort(message.getPort());
		failure.setPingable(message.getPingable());
		failure.setMacable(message.getMacable());
		failure.setStatsable(message.getStatsable());
		failure.setPoolsable(message.getPoolsable());
		failure.setSummaryable(message.getSummaryable());
		failure.setDetectTime(message.getExecuteTime());
		return failure;
	}
	
	private static String processStats(String str) {
		int index;
		while((index = str.indexOf("}{"))!=-1){
			String str1 = str.substring(0, index+1);
			String str2 = str.substring(index+1,str.length());
			str = str1 + "," + str2;
		}
		return str;
	}

	private static Double getDouble(JsonObject stats, String propName) {
		if(stats==null){
			return (double) 0;
		}
		if(StringUtils.isEmpty(propName)){
			return (double) 0;
		}
		try {
			return stats.get(propName).getAsDouble();
		} catch (Exception e) {
			return (double) 0;
		}
	}

	private static int getInt(JsonObject stats, String propName) {
		if(stats==null){
			return 0;
		}
		if(StringUtils.isEmpty(propName)){
			return 0;
		}
		try {
			return stats.get(propName).getAsInt();
		} catch (Exception e) {
			return 0;
		}
	}

	private static long getLong(JsonObject stats, String propName) {
		if(stats==null){
			return 0;
		}
		if(StringUtils.isBlank(propName)){
			return 0;
		}
		try {
			return stats.get(propName).getAsLong();
		} catch (Exception e) {
			return 0;
		}
	}

	private static String getString(JsonObject stats, String propName) {
		if(stats==null){
			return null;
		}
		if(StringUtils.isBlank(propName)){
			return null;
		}
		try {
			return stats.get(propName).getAsString();
		} catch (Exception e) {
			return null;
		}
	}


	

}
